---
title: Dark Mode
description: This page describes how to enable dark mode behavior in your app. The dark mode can be enabled globally, conditionally, or the user's system preference.
docType: Article
docGroup: Customization
keywords: [dark mode, color scheme, Sass]
---

import { DarkModeColors } from "./DarkModeColors.tsx";

# Dark Mode

There are a few different type of light/dark themes that can be available for a
web application:

- Light Only
- Dark Only
- System Preference
- Light/Dark Mode Toggle
- Light/Dark/System Toggle

> !Info! This page will guide you through all the approaches except for the
> "Light Only" theme since that is the default behavior. Check out the
> [theme customization documentation](./theme) for more theme behavior.

If the application should only use a dark theme, set the [$SASSDOC](color-scheme)
variable to `dark` when importing the `react-md` styles which will generate all
styles with the dark theme variants.

```scss
@use "@react-md/core" with (
  $color-scheme: dark
);

@include core.styles;
```

Enabling the dark mode will change all the theme colors to their dark-mode
variants and exclude any light theme behavior from the generated CSS. The
default theme colors are:

<DarkModeColors />

### Dark Elevation Colors

When the dark mode is enabled, the surface background color will become lighter
as the `z-index`/`box-shadow` increases to enable more contrast between
temporary elements. Here is a list of components in `react-md` and their elevation:

| Name                | Elevation |
| ------------------- | --------- |
| `AppBar`            | `2`       |
| `Card`              | `2`       |
| `Sheet` (inline)    | `2`       |
| `StickyTableHeader` | `4`       |
| `Chip`              | `8`       |
| `Toast`             | `6`       |
| `Menu`              | `8`       |
| `Dialog`            | `16`      |
| `Sheet` (normal)    | `16`      |

### Configuring Elevation Colors

The different elevation colors can be changed by modifying the
[$SASSDOC](dark-elevation-colors) map. The next demo shows all 25 elevation
colors and allows the values to be modified to see how they behave.

```demo source="./DarkElevationColors.tsx" disableBox startOnScss forceDarkMode disablePadding

```

## System Mode

If the application should use the dark theme only if the user has set their
system preference to dark, set the [$SASSDOC](color-scheme) to `system`. The
generated styles will default to the light theme but add a media query to use
the dark theme when the `@media (prefers-color-scheme: dark)` matches.

```scss
@use "@react-md/core" with (
  $color-scheme: system
);

@include core.styles;
```

## Light or Dark Mode

If the application allows the user to select the current color scheme, generate
the styles as normal with the default color scheme and create a global class
name with the alternative theme using the [$SASSDOC](use-light-theme) or
[$SASSDOC](use-dark-theme) mixins.

Once the styles are generated, the app should be wrapped in the
[LocalStorageColorSchemeProvider](/components/color-scheme-provider#local-storage-example)
or a custom
[Cookie Storage Provider](/components/color-scheme-provider#cookie-storage-example)
and apply the light or dark theme class name to the root html as needed. The
following examples will use the `LocalStorageColorSchemeProvider` to keep it simple.

Start by configuring the default [$SASSDOC](color-scheme) and creating a class
name for the other color scheme. This example will default to a `light` theme
and allow the user to configure it to be `dark`.

```scss
@use "@react-md/core" with (
  // If the $color-scheme is not set or set to `light`, the dark elevation
  // styles are omitted by default to keep the bundle smaller. So when enabling
  // a toggleable dark mode, force the styles to be created:
  $disable-dark-elevation: false
);

@include core.styles;

.dark-theme {
  @include core.dark-theme;
}

// if you want to default with a dark theme instead:
@use "@react-md/core" with (
  $color-scheme: dark
);

@include core.styles;

.light-theme {
  @include core.light-theme;
}
```

Wrap the app in the chosen `ColorSchemeProvider` implementation:

```tsx
import { LocalStorageColorSchemeProvider } from "@react-md/core/theme/LocalStorageColorSchemeProvider";

function App() {
  return (
    <LocalStorageColorSchemeProvider>
      <RestOfTheApp />
      <ApplyTheme />
    </LocalStorageColorSchemeProvider>
  );
}
```

Change the styles based on the color scheme:

```tsx
import { useColorScheme } from "@react-md/core/theme/useColorScheme";
import { useHtmlClassName } from "@react-md/core/useHtmlClassName";

function ApplyTheme() {
  const { currentColor, setColorScheme } = useColorScheme();
  useHtmlClassName(currentColor === "dark" ? "dark-theme" : "");

  // Whatever UI is desired for this
  return (
    <Button
      onClick={() =>
        setColorScheme((prev) => (prev === "light" ? "dark" : "light"))
      }
    >
      Theme
    </Button>
  );
}
```

## Light or Dark or System Mode

The style setup will be about the same as the previous examples. Start by
defining the default [$SASSDOC](color-scheme) and create additional classes for the
other color schemes.

```scss
@use "@react-md/core" with (
  $color-scheme: light
);

@include core.styles;

.dark-theme {
  @include core.dark-theme;
}

@media (prefers-color-scheme: dark) {
  .system-theme {
    @include core.dark-theme;
  }
}
```

Then apply the `dark-theme` or `system-theme` class name when needed:

```tsx
import { useColorScheme } from "@react-md/core/theme/useColorScheme";
import { useHtmlClassName } from "@react-md/core/useHtmlClassName";
import { cnb } from "cnbuilder";

function ApplyTheme() {
  const { colorScheme } = useColorScheme();
  useHtmlClassName(cnb(colorScheme !== "light" && `${colorScheme}-theme`));
  return null;
}
```

### This Website's Implementation

If a real-world example is useful, here's this website's implementation
with next.js:

```import source="@/components/CookieColorSchemeProvider.tsx" fileName="src/components/CookieColorSchemeProvider.tsx"

```

```import source="@/utils/clientCookies.ts" fileName="src/utils/clientCookies.ts"

```

```tsx fileName="src/components/RootLayout.tsx"
import { CoreProviders } from "@react-md/core/CoreProviders";
import { RootHtml } from "@react-md/core/RootHtml";
import { MenuConfigurationProvider } from "@react-md/core/menu/MenuConfigurationProvider";
import { NullSuspense } from "@react-md/core/suspense/NullSuspense";
import { isColorScheme } from "@react-md/core/theme/isColorScheme";
import { cnb } from "cnbuilder";
import { Roboto_Flex } from "next/font/google";
import { cookies } from "next/headers.js";
import { type ReactElement, type ReactNode } from "react";

import { CookieColorSchemeProvider } from "@/components/CookieColorSchemeProvider.jsx";
import { LoadThemeStyles } from "@/components/LoadThemeStyles.jsx";
import { COLOR_SCHEME_KEY } from "@/constants/cookies.js";
import { rmdConfig } from "@/constants/rmdConfig.jsx";

import "./layout.scss";

export { metadata } from "@/constants/metadata.js";

const roboto = Roboto_Flex({
  subsets: ["latin"],
  display: "swap",
  variable: "--roboto",
});

export interface RootLayoutProps {
  children: ReactNode;
}

export function RootLayout({ children }: RootLayoutProps): ReactElement {
  const colorSchemeCookie = cookies().get(COLOR_SCHEME_KEY)?.value;
  const defaultColorScheme = isColorScheme(colorSchemeCookie)
    ? colorScheme
    : "system";

  return (
    <RootHtml className={cnb(roboto.variable, `${defaultColorScheme}-theme`)}>
      <CoreProviders {...rmdConfig}>
        <MenuConfigurationProvider renderAsSheet="phone">
          <CookieColorSchemeProvider defaultColorScheme={defaultColorScheme}>
            <NullSuspense>
              <LoadThemeStyles />
            </NullSuspense>
            <MainLayout>{children}</MainLayout>
          </CookieColorSchemeProvider>
        </MenuConfigurationProvider>
      </CoreProviders>
    </RootHtml>
  );
}
```

```tsx fileName="src/components/LoadThemeStyles.tsx"
"use client";

import { useColorScheme } from "@react-md/core/theme/useColorScheme";
import { useHtmlClassName } from "@react-md/core/useHtmlClassName";

export function LoadThemeStyles(): null {
  const { colorScheme } = useColorScheme();
  useHtmlClassName(`${colorScheme}-theme`);
  return null;
}
```
